dump("// $Id: testing.js,v 1.20 2007/02/22 13:56:56 Will Exp $;\n");
var baseUrl = "chrome://jsunit/content/tests";  // We need to use 'jsunit' rather than 'viewmycurrency' to prevent conversion of the test pages

function coreTestSuite() {
  var newsuite = new top.jsUnitTestSuite();
  newsuite.addTestPage(baseUrl+'/test_NumberConversion.html');
  //WILL: TODO: put this back. Currently a bug if LOG window is displayed. (VMC tries to convert about:blank) newsuite.addTestPage(baseUrl+'/test_big-table_bug_node-arrays-do-not-match.html');
  return newsuite;
}

function convertPagesSuite() {
  var newsuite = new top.jsUnitTestSuite();
  newsuite.addTestPage(baseUrl+'/testConvertPageEurozone.html');
  return newsuite;
}


//WILL: TODO: turn this into proper object
function WILLTEST_HelperFuncs() {
  var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
    .getService(Components.interfaces.nsIWindowMediator);
  var browserWindow = wm.getMostRecentWindow("navigator:browser");

  this.VMC = browserWindow.VMC;
  //W: this.viewMyCurrencyGui = browserWindow.VMC.gViewMyCurrencyGui;

  if (browserWindow.VMC.gui) {
    this.viewMyCurrency = browserWindow.VMC.gui._viewMyCurrency;
  } else {
    this.viewMyCurrency = null; // VMC is not enabled in this browser
  }

  //WILL: this is an aweful hack. Why doesn't Javascript support a blocking wait() that does not sleep the entire Javascript interpreter!
  this.sleep = function(delayMs) {
    window.openDialog('chrome://viewmycurrency/content/tests/SleepWindow.xul','VMC.Sleep','chrome,modal', delayMs);
  };


  // used by create asserts below:
  function createObj(/* comment, constructor, args... */) {

    var args = [];
    this.VMC.applyFuncToArray( function(item) { args.push(item); },arguments); // JS annoyance: arguments is not a real array
    
    var comment         = args.shift();
    var ConstructorFunc = args.shift();
    
    //check the args
    top.assertEquals(   'Comment must be a string!', 'string', (typeof comment)         );
    this.assertValidRef( comment+': Constructor not found ',             ConstructorFunc );
    
    var obj;
    var excep;
    try {
      var emptyObj = new ConstructorFunc('empty');
      obj = ConstructorFunc.apply(emptyObj,args); // Turn obj into the target object type
    } catch (e) {
      excep=e;
    }
    var evalStr = ConstructorFunc.name +'('+ args +')';  //Array.toString() is rubbish - it doesn't indicate sub-arrays
    return {obj:obj, excep:excep, report:comment+': '+evalStr };
    // no checks - the caller does that
  }


//************************ New Asserts *****************************************

  this.assertCausesException = function(commnet,func) {
    //WILL: do I still need venkman mode?
    try {
      func();
    } catch (e) {
      return; // we got our exception as expected
    }
    top.assert('Missing expected exception for '+comment,false);
  };
  
  this.assertFailCreateObject = function() {
    if (! this.traceTest.deleberateExceptionsAllowed) {
      warn("Skipping assertFailCreateObject() - Venkman mode");
      return;
    }
    var r=createObj.apply(this,arguments);
    top.assertNotNull(   r.report +' should raise an exception',       r.excep );
    top.assertUndefined( r.report +' should not have created: '+r.obj, r.obj   );  
  };
  
  this.assertCreateObject = function() {
    var r=createObj.apply(this,arguments);
    top.assertUndefined( r.report +' should NOT raise an exception',r.excep );
    this.assertValidRef(  r.report +' should have created object',   r.obj   );
    return r.obj;
  }; 

  this.assertValidRef = function(comment,value) {
    top.assertNotNull(comment,value);
    top.assertNotUndefined(comment,value);
  };
  
  //WILL: TODO: this could just be assertObjectsEqual
  this.assertArraysEqual = function(expected,actual,comment) {
    this.assertValidRef(comment+': not valid array', expected);
    this.assertValidRef(comment+': not valid array', actual);
    top.assertEquals(comment+': different lengths', expected.length, actual.length);
    for (var i=0;i<expected.length;++i) {
      top.assertEquals(comment+': value['+i+'] differ', expected[i], actual[i]);
    }
  };
  
  //WILL: TODO: understand why I need to use top 

  
  function red(message)  { return '<font color="red">' + message + '</font>'; }
  function bold(message) { return '<b>' +                message + '</b>';    }
  
  this.traceTest = function(message) {
    var testName = arguments.callee.caller.name;
    if ( /AttemptInvalid/.test(testName) && ! this.traceTest.deleberateExceptionsAllowed) {
      top.warn(red('Venkman mode. Skipping: '+testName));
      return false;
    }
    if (this.traceTest.limitTo && (this.traceTest.limitTo.indexOf(testName)==-1)) {
      top.warn(red('Test Bug only mode. Skipping: '+bold(testName)));
      return false;
    }
    
    top.info('Test: ' + bold(testName) + ' ('+message+')' );
    return true;
  }
  this.traceTest.limitTo = '';
  this.traceTest.deleberateExceptionsAllowed = true;
  

  this.newListFromCodes = function(codes) {
    var completeList = this.VMC.currencyDB.getCompleteList();
    var currencyList = completeList.createListFromCodes(codes);
    this.assertValidRef('creating list '+codes, currencyList);
    return currencyList;
  };

}




function suite() {
  var WILLTEST = new WILLTEST_HelperFuncs();
  top.WILLTEST = WILLTEST; // store it in the browser so that all testpages can access the helper

  var viewMyCurrency = top.WILLTEST.viewMyCurrency;
  if (viewMyCurrency) {
    // set some default conditions for the tests
    viewMyCurrency.disableConversion();
    viewMyCurrency.tooltipMode = false;
  }

  var newsuite = new top.jsUnitTestSuite();
  newsuite.addTestSuite(coreTestSuite());
  newsuite.addTestSuite(convertPagesSuite());
  return newsuite;
}
